import { Node, UITransform, v2, v3, Vec2 } from "cc";
import { ecs } from "db://app-game/libs/ecs/ECS";
import FlowGrid from "db://app-game/libs/math/pathfinding/flow-field/FlowGrid";
import RVOMath from "db://app-game/libs/math/rov2/RVOMath";
import Simulator from "db://app-game/libs/math/rov2/Simulator";
import Vector2D from "db://app-game/libs/math/rov2/Vector2D";
import { smc } from "../model/SingletonModuleComp";

/** 移动模式 */
export enum MoveModel {
  /** 流动网格移动 */
  FlowGridMove = 0,
  /** A星寻路移动  */
  AStarMove = 1,
}

/** 移动组件模组 */
@ecs.register("MoveToModel")
export class MoveToModelComp extends ecs.Comp {
  id: number = -1;
  /** 移动节点 */
  node: Node;
  /** 移动地图节点——坐标转换作用 */
  map: Node;
  /** 移动速度 */
  speed: number = 0;
  /** 偏移距离 */
  offset: number = 0;
  /** 移动模式 */
  moveModel: MoveModel = MoveModel.FlowGridMove;
  /** 移动目标位置 */
  goal: Vector2D = new Vector2D(0, 0);
  /** 终点位置 */
  end: Vector2D = new Vector2D(0, 0);
  /** 流动网格 */
  flowGrid: FlowGrid;
  /** 模拟器 */
  simulator: Simulator;

  reset(entity: ecs.Entity): void {
    this.id = -1;
    this.node = null!;
    this.map = null!;
    this.speed = 0;
    this.offset = 0;
    this.moveModel = MoveModel.FlowGridMove;
    this.goal = new Vector2D(0, 0);
    this.end = new Vector2D(0, 0);
    this.simulator = null!;
    this.flowGrid = null;
  }
}

/** 移动备份信息 */
@ecs.register("moveInfoBackups")
export class moveInfoBackupsComp extends ecs.Comp {
  id: number = -1;
  /** 移动节点 */
  node: Node;
  /** 移动地图节点——坐标转换作用 */
  map: Node;
  reset(entity: ecs.Entity): void {
    this.id = -1;
  }
}

/** 移动系统 */
@ecs.register("MoveTo")
export class MoveToSystem
  extends ecs.ComblockSystem
  implements ecs.IEntityEnterSystem, ecs.ISystemUpdate
{
  filter(): ecs.IMatcher {
    return ecs.allOf(MoveToModelComp);
  }

  entityEnter(entity: ecs.Entity): void {
    // 把移动节点加入模拟器
    const move = entity.get(MoveToModelComp);
    const backupsInfo = entity.get(moveInfoBackupsComp);
    let id = !backupsInfo ? move.simulator.addAgent(null) : backupsInfo.id;
    const pos = this.posConvert(move.node, move.map);
    move.simulator.setAgentPosition(id, pos.x, pos.y);
    move.id = id;
  }

  update(entity: ecs.Entity, dt: number): void {
    const move = entity.get(MoveToModelComp);
    const pos = this.posConvert(move.node, move.map);
    const flowGrid = smc.level.map.MapRenderModel.flowGrid;
    // 流动网格移动
    if (
      move.moveModel == MoveModel.FlowGridMove &&
      flowGrid instanceof FlowGrid
    ) {
      move.end = new Vector2D(flowGrid.goal.x, flowGrid.goal.y);
      // 检查是否到达终点

      if (RVOMath.absSq(move.end.minus(pos)) < move.offset) {
        this.exit(entity);
      } else {
        const flowGridNode = flowGrid.getVectorAt(v2(pos.x, pos.y));
        if (!flowGridNode) return;
        //1.获取方向向量
        const direction = new Vec2(flowGridNode.x, -flowGridNode.y);
        // // 2.归一化向量
        const normalizedDir = direction.normalize();
        // // 3.计算移动量
        const movement = normalizedDir.multiplyScalar(20);
        // console.log("移动量", movement, normalizedDir);

        const newPos = pos.plus(new Vector2D(movement.x, movement.y));
        // move.node.translate(v3(normalizedDir.x, normalizedDir.y));
        move.simulator.setAgentGoal(move.id, newPos.x, newPos.y);
        const agentPos = move.simulator.getAgentPosition(move.id);
        move.node.setPosition(agentPos.x, agentPos.y);
      }
    }
  }

  /** 坐标转换 */
  posConvert(node: Node, map: Node): Vector2D {
    let wPos = node
      .getComponent(UITransform)
      .convertToWorldSpaceAR(v3(0, 0, 0));

    let pos = map.getComponent(UITransform).convertToNodeSpaceAR(wPos);
    return new Vector2D(pos.x, pos.y);
  }

  /** 移动完成出口 */
  private exit(entity: ecs.Entity) {
    entity.remove(MoveToModelComp);
  }
}
